#  This file is part of FlickFleck.
#  Copyright (C) 2008 Jyke Tapani Jokinen
#
#    FlickFleck is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    FlickFleck is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with FlickFleck.  If not, see <http://www.gnu.org/licenses/>.
#
import config
import sys, os, os.path
import ui
import types
import fnmatch
import i18n
import jpegops
import fileops
from subprocess import Popen, PIPE

class PhotoCopier:
    def __init__(self):
        pass

    def init(self):
        # what external binary to use
        cmd_j = self.findexe( config.jpegtran )
        cmd_e = self.findexe( config.exiftool )

        # how to execute the binary
        if sys.platform == 'win32':
            # 'call' found in bugs.python.org/issue1524
            config.jpegtran = 'call ' + fileops.quotepath( cmd_j )
            config.exiftool = 'call ' + fileops.quotepath( cmd_e )
        else:
            config.jpegtran = cmd_j
            config.exiftool = cmd_e

        self.init_filelist()

    #
    # called at program startup
    #
    def init_filelist(self):
        #
        # find all jpeg-files
        # fromdir can be a list of directories (all are scanned)
        #
        self._frompaths = []
        if type(config.fromdir) == types.ListType:
            for dir in config.fromdir:
                self.addsourcefiles(dir)
        else:
            self.addsourcefiles(config.fromdir)

        # tell number of found files to the user and the progressbar
        numitems = len(self._frompaths)
        ui.status( i18n.name['status_found'] + " " + str( numitems )
                   + " " + i18n.name['status_files'] )
        ui.wins.pb.init( numitems )

    # finds all jpegs under 'dir'
    # definition of a jpeg is config.jpegglob
    def addsourcefiles(self, dir):
        for root,dirs,files in os.walk( dir ):
            if len(files) == 0:
                continue
            for filt in config.jpegglob:
                found = fnmatch.filter( files, filt )
                if len(found) > 0:
                    for name in found:
                        self._frompaths.append( os.path.join( root, name ) )

    # ----------------------------------------------------------------------
    def findexe(self, programname):
        # if an absolute pathname is configured, use that:
        if os.path.isabs( programname ):
            return programname

        #
        # if the executable is found in FlickFlecks binary dir, use that
        #
        tool = config.installdir + os.sep + config.bindir \
                + os.sep + programname
        if os.access( tool, os.X_OK ):
            return tool

        #
        # if we can execute the program then it's in the path, use that
        # 
        else:
            cmd = programname + " NOSUCHFILEEXITS"
            pipe = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
            pipe.wait()
            #
            # on Windows only 0 means we could execute the program
            # (XXX: these test are ad hoc, traversing PATH would be better)
            if sys.platform == 'win32':
                if pipe.returncode == 0:
                    return programname
            #
            # on UNIX we can execute the program and it can give 1 as error
            # return code (bad parameter)
            #
            elif 0 <= pipe.returncode <= 1:
                return programname

        ui.ERR( ("cannot find executable %s" % programname) )


    # ----------------------------------------------------------------------
    # user started the operations
    #
    def start(self):
        if len( self._frompaths) == 0:
            ui.ERR("No files to copy")
        
        from fileops import copy
        dst = config.todir
        if not os.path.exists( dst ):
            ui.ERR("Target directory (%s) does not exists" % dst)
        
	self._newnames = []

        # -------- copy files to new location and name ---------------
        ui.status( i18n.name['status_copying'] )
        ui.wins.pb.clear() # reset progressbar

        for src in self._frompaths:
            (newdir,newname) = jpegops.newname( src )
            ui.checkStop()    # was operation cancelled by user
            ui.wins.pb.step() # step progressbar

            targetNOTok = True
            silentskip  = False
            counter = 0
            # if the targetfilename already exists, increase the counter
            # and add it to the generated filename
            # loop until unique name is found
            while targetNOTok:
                if config.targetdirs == True:
                    to = dst + os.path.sep + newdir + os.path.sep + newname
                else:
                    to = dst + os.path.sep + newname

                if counter > 0:
                    to += "-" + str(counter)

                to += ".jpg"
                if os.access( to, os.F_OK ):
                    if hasattr(config, 'silentskip'):
                        silentskip = True
                        targetNOTok = False
                        
                    if counter > 999:
                        ui.ERR( "cannot transfer file: %s" % src )
                    counter = counter + 1
                else:
                    targetNOTok = False
            # end while
            if silentskip: continue

            # make target subdirs if not already made
            if config.targetdirs == True:
                path = dst + os.path.sep
                for dir in newdir.split( os.path.sep ):
                    path += dir + os.path.sep
                    if not os.path.exists( path ):
                        os.mkdir( path )

            # save the targetfilename for rotation operations
            self._newnames.append( to )
            copy( src, to )

        # ------------ rotate files -------------
        ui.status( i18n.name['status_rotating'] )
        ui.wins.pb.clear() # reset progressbar

        for file in self._newnames:
            jpegops.rotate( file )
            ui.checkStop()    # was operation cancelled by user
            ui.wins.pb.step() # update progressbar

        ui.status( i18n.name['status_done'] )
        ui.Ready()
        
